#include "gtest.h"

#include "gmock.h"


::testing::AssertionResult e(void)
{
	return ::testing::AssertionFailure() << "THROWING EXCEPTION AT " << __FILE__ << ":" << __LINE__;
}
//#define throw EXPECT_TRUE(e()); throw
#include "Sorter.h"

class TestFixtures: public ::testing::Test
{public:

	TestFixtures(){;}


	void SetUp()
	{
		const ::testing::TestInfo* const no =
		::testing::UnitTest::GetInstance()->current_test_info();
		if ( !strcmp("EXCEPTION_TEST3",no->name()) )
			throw int(0);
	}
	void TearDown()
	{

		const ::testing::TestInfo* const no = ::testing::UnitTest::GetInstance()->current_test_info();

		std::string str(no->name());
		if ( "EXCEPTION_TEST5" == str || "EXCEPTION_TEST6" == str )
		{
			throw this;
		}
	}
};

void justthrowexception()
{
	throw std::string("NO");
}

TEST_F(TestFixtures,EXCEPTION_TEST1)//EXCEPTION IN TEST BODY
{


	EXPECT_NO_THROW((justthrowexception()));


}

TEST_F(TestFixtures,EXCEPTION_TEST)//NO EXCPETION
{
	;
}

//EXCETION IN TEST BODY AS WELL AS IN TEARDOWN BOTH SHOULD BE REPORTED.
TEST_F(TestFixtures,EXCEPTION_TEST5)
{
	EXPECT_THROW(justthrowexception(),int);
}

TEST_F(TestFixtures,EXCEPTION_TEST6)//EXCEPTION ONLY IN CLEANUP.
{
	;
}

TEST_F(TestFixtures,EXCEPTION_TEST3)//EXCETION IN SETUP SO TEST BODY SHOULD NOT BE RUN

{
	ASSERT_FALSE(true);
}

TEST(SORTERTEST,SORTER)//SAMPLE TEST
{
	int arr[] = { 9, 0 , 2, 1, 4 };
	Sorter<int>* a = new Sorter<int>;
	int len = 5;
	for ( int i = 0 ; i < len ; i++)
	{
		a->add(arr[i]);


	}

	int *ptr = 0;
	(a->sort());
	a->getArray(ptr);
	for ( int i = 0; i < len - 1 ; i++)
	{
		if ( ptr[i] > ptr[i+1] )
		{
			EXPECT_TRUE(false);
		}
	}
}

int exitwithcode(int i)
{
	int *ptr = NULL; *ptr = 1;
	exit (i);
}

TEST(DEATHTESTS,Testno) // DEATH TEST AND SIGNAL TEST
{
	EXPECT_EXIT(exitwithcode(1),::testing::KilledBySignal(SIGSEGV),"");
	EXPECT_DEATH({int * ptr = NULL; *ptr = 1;},"");
}

template <typename T> class TemplatesTest : public ::testing::Test{};
typedef ::testing::Types<short,int,long> types;
TYPED_TEST_CASE(TemplatesTest,types);// Testing Template class for multiple types
TYPED_TEST(TemplatesTest,SortTest)
{
	TypeParam arr[] = { 9, 0 , 2, 1, 4 };


	Sorter<TypeParam>* a = new Sorter<TypeParam>;
	int len = 5;
	for ( int i = 0 ; i < len ; i++)
	{
		a->add(arr[i]);
	}
	TypeParam *ptr = 0;
	(a->sort());
	a->getArray(ptr);
	for ( int i = 0; i < len - 1 ; i++)
	{
		if ( ptr[i] > ptr[i+1] )
			EXPECT_TRUE(false);
	}
}
int main(int argc,char** argv)
{
	::testing::InitGoogleMock(&argc,argv);
	::testing::InitGoogleTest(&argc,argv);
	return RUN_ALL_TESTS();
}
